/**
 *  Loads an NLogo Model  file into  so we can retrieve all the widgets that compose it.
 *
 * 
 *   @author NetLogo
 */

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;

import model.*;

public final strictfp class ModelReader
{

	public  static final int SLIDER_NAME_OFFSET = 6;
	public  static final int SLIDER_MIN_OFFSET = 7;
	public  static final int SLIDER_MAX_OFFSET = 8;
	public static int levels =5;
	
	private static String readFile(File file) throws IOException {
		   String lineSep = System.getProperty("line.separator");
		   BufferedReader br = new BufferedReader(new FileReader(file));
		   String nextLine = "";
		   StringBuffer sb = new StringBuffer();
		   while ((nextLine = br.readLine()) != null) {
		     sb.append(nextLine);
		     //
		     // note:
		     //   BufferedReader strips the EOL character
		     //   so we add a new one!
		     //
		     sb.append(lineSep);
		   }
		   return sb.toString();
		}
	
	public static ParameterHashMap getParameterHashMap(File file)
	{
		String source = new String(""); // TODO Put it in a String
		try {
			source = readFile(file);
		} catch (IOException e) {

			e.printStackTrace();
		}
			System.out.println("Loaded");
			Map<Section, String[]> list = ModelReader.parseString( source );
			//System.out.println(java.util.Arrays.deepToString(list.values().toArray()));
            String[] widgetSectionArray = list.get(Section.WIDGETS);
			//System.out.println(widgetSectionArray);
            ParameterHashMap parameterHashMap = new ParameterHashMap();

			for ( int i=1;  i<widgetSectionArray.length;  i++)
			{
				String widgetItem = widgetSectionArray[i];
				widgetItem = widgetItem.toUpperCase() ;

				//System.out.println(widgetItem);
				if( widgetItem.equals( "SLIDER" ) )
				{
	                 // FIXME: check to se if the type should be
	                 // DoubleDiscreteSpec instead of DoubleLevelSpec
					String name = widgetSectionArray[i+SLIDER_NAME_OFFSET];
                    String min = widgetSectionArray[i+SLIDER_MIN_OFFSET];
                    String max = widgetSectionArray[i+SLIDER_MAX_OFFSET];
					Double minDouble =  Double.valueOf(min);
					Double maxDouble = Double.valueOf(max);
					Double stepDouble = (Math.abs(maxDouble) - Math.abs(minDouble)) / levels;
                    DoubleDiscreteSpec s = new DoubleDiscreteSpec(name, minDouble, stepDouble, maxDouble);
                    parameterHashMap.put(name,s);
				}
				else if( widgetItem.equals( "CHOOSER" ) || // current name
						 widgetItem.equals( "CHOICE" ) )   // old name, used in old models
				{
					// Get Min & Max
				}
				else if( widgetItem.equals( "BUTTON" ) )
				{
					// Get Min & Max
				}
				else if( widgetItem.equals( "PLOT" ) )
				{
					// Get Min & Max
				}
				else if( widgetItem.equals( "SWITCH" ) )
				{
					// Get Min & Max
				}
				else if( widgetItem.equals( "MONITOR" ) )
				{
					// Get Min & Max
				}
				else if( widgetItem.equals( "INPUT" ) ||  // in the GUI, it's "Input Box"
						 widgetItem.equals( "INPUTBOX" ) )  // in saved models, it's "INPUTBOX"
				{
					// Get Min & Max
				}
				else if( widgetItem.equals( "OUTPUT" ) )  // currently in saved models only - ST 3/17/04
				{
					// Get Min & Max
				}
				// Get Min & Max
				else
				{
					//throw new IllegalStateException
					//	( "unknown widget type: " + type ) ;
				}
			}
            return parameterHashMap;
	}
	
	
	// this class is not instantiable
	private ModelReader() { throw new IllegalStateException() ; }

	public enum Section
    {
		SOURCE , WIDGETS , INFO , SHAPES , VERSION , PREVIEW_COMMANDS ,
		AGGREGATE , EXPERIMENTS , CLIENT , LINK_SHAPES
	}

	public static final String SEPARATOR = "@#$#@#$#@";

	public static Set<Section> getSections()
	{
		return java.util.EnumSet.allOf( Section.class ) ;
	}

	public static Map<Section,String[]> parseString( String string )
	{
		return parseString( string , true ) ;
	}

	public static Map<Section,String[]> parseString( String string , boolean checkVersion )
	{
		try
		{
			Map<Section,String[]> map = new HashMap<Section,String[]>() ;
			for( Section section : getSections() )
			{
				map.put( section , new String[] { } ) ;
			}
			java.io.BufferedReader br = new java.io.BufferedReader(new java.io.StringReader(string));
			Iterator<Section> sectionsIter = getSections().iterator() ;
			List<String> sectionContents = new ArrayList<String>() ;
			while( sectionsIter.hasNext() )
			{
				String str = br.readLine();
				if( str == null || str.startsWith( SEPARATOR ) )
				{
					map.put( sectionsIter.next() ,
							 sectionContents.toArray( new String[] { } ) ) ;
					if (str == null) { break ; }
					sectionContents.clear() ;
				}
				else
				{
					sectionContents.add( str ) ;
				}
			}
			// Handle invalid files
			if( checkVersion && map.get( Section.VERSION ).length == 0 )
			{
				return null ;
			}
			return map ;
		}
		catch( java.io.IOException e )
		{
			throw new IllegalStateException( e ) ;
		}
	}

	public static List<List<String>> parseWidgets( String[] widgets )
	{
		int index = 0 ;
		List<List<String>> ret =
			new ArrayList<List<String>>() ;
		while( ( widgets.length > index ) &&
			   ( 0 == getString( widgets , index ).length() ) )
		{
			index++ ;
		}
		List<String> res = new ArrayList<String>() ;
		while( widgets.length > index )
		{
			String s = getString( widgets , index ) ;
			if( 0 != s.length() )
			{
				res.add( s ) ;
			}
			else
			{
				// avoid blank lines
				boolean blank = true ;
				for( int i = 0 ; res.size() != i ; i++ )
				{
					String elem = res.get( i ).toString();
					if ( elem.length() != 0 )
					{
						blank = false ;
						break ;
					}
				}
				if ( !blank )
				{
					ret.add( res ) ;
				}
				res = new ArrayList<String>() ;
			}
			index++ ;
		}
		return ret ;
	}

	public static String getString( String[] v , int index )
	{
		if( ( null != v ) && ( v.length > index ) )
		{
			return v[ index ] ;
		}
		return "" ;
	}

	public static String parseVersion( Map<Section,String[]> map )
	{
		return map.get( Section.VERSION )[ 0 ] ;
	}

    public static void main(String[] args)
    {
        File file = new File("wolf.nlogo");
		ModelReader.getParameterHashMap(file);
	}
}
